﻿using Microsoft.Rtc.Collaboration;
using Microsoft.Rtc.Collaboration.ConferenceManagement;
using Microsoft.Rtc.Signaling;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace MSFT_SAMPLE_ConferencingServiceLibrary
{
    class MeetingInstance : IDisposable
    {

        public string _userUri;
        private string _appID;
        public bool verbose = true;
        private UserEndpoint _userEndpoint;
        private UCMAUtil _helper;
        private Timer selfDestruct;
        bool disposed = false;
        
        

        public void Init(string userUri, UCMAUtil helper)
        {
            
            this._appID = "MeetingScheduler";
            this._helper = helper;
            this._userUri = userUri;
            this.Trace("Registering User Endpoint...");
            this._userEndpoint = this._helper.CreateUserEndpoint(_userUri);
            this._helper.EstablishUserEndpoint(this._userEndpoint);
            this.Trace("Init user: " + userUri);
            this.Trace("EndpointCount:" + _userEndpoint.Platform.ConnectionManager.EndpointsCount);
            this.selfDestruct = new Timer(60000);
            this.selfDestruct.Elapsed += selfDestruct_Elapsed;
            this.selfDestruct.Start();
        }

        
        public List<ConferenceItem> GetConferences(SchedulingTemplate template)
        {
            List<ConferenceItem> conferenceResults = new List<ConferenceItem>();
            this.Trace("Getting conferences");
            IAsyncResult asyncResultSummary = _userEndpoint.ConferenceServices.BeginGetConferenceSummaries(template, null, null);
            Collection<ConferenceSummary> summaries =_userEndpoint.ConferenceServices.EndGetConferenceSummaries(asyncResultSummary);
                    foreach (ConferenceSummary summary in summaries)
                    {
                        IAsyncResult asyncResultDetails = _userEndpoint.ConferenceServices.BeginGetConference(summary.ConferenceId,null,null);
                        Conference conferenceDetail =_userEndpoint.ConferenceServices.EndGetConference(asyncResultDetails);
                        ConferenceItem _conference = DataUtilities.UCMAConf2SimpleConf(conferenceDetail);
                        conferenceResults.Add(_conference);
                        
                    }
            this.Trace("Finished Getting conferences");
            return conferenceResults;
        }

        public void CreatStaticConference()
        {
            ConferenceScheduleInformation info = new ConferenceScheduleInformation(SchedulingTemplate.AdministratorSupplied);

            _userEndpoint.ConferenceServices.BeginScheduleConference(info,
            result =>
            {
                Conference conf = _userEndpoint.ConferenceServices.EndScheduleConference(result);
                Trace(conf.WebUrl);
            }, null);
        }

        public ConferenceItem CreatNewConference(ConferenceItem _conf)
        { 
            ConferenceScheduleInformation con = DataUtilities.SimpleConf2UCMAConfInfo(_conf);
            IAsyncResult asyncNewConf = _userEndpoint.ConferenceServices.BeginScheduleConference(con, null, null);
            Conference conf = _userEndpoint.ConferenceServices.EndScheduleConference(asyncNewConf);
            Trace(conf.WebUrl);
            return DataUtilities.UCMAConf2SimpleConf(conf);
        }

        public string CancelMeeting(string conferenceId)
        {
            IAsyncResult asyncCancelConf =_userEndpoint.ConferenceServices.BeginCancelConference(conferenceId,null,null);
            _userEndpoint.ConferenceServices.EndCancelConference(asyncCancelConf);
            Trace("Removed:" + conferenceId);
            return conferenceId;
        }

        public void CancelMeetingStatic(string conferenceId)
        {
            _userEndpoint.ConferenceServices.BeginCancelConference(conferenceId, SchedulingTemplate.AdministratorSupplied,
            result =>
            {
                _userEndpoint.ConferenceServices.EndCancelConference(result);
                Trace("Removed:" + conferenceId);
            }, null);
        }

        public string ResetUserStaticConference(string userURI)
        {

           IAsyncResult asyncResetStatic = _userEndpoint.ConferenceServices.BeginGetConferenceSummaries(SchedulingTemplate.AdministratorSupplied,null,null);
           Collection<ConferenceSummary> summaries = _userEndpoint.ConferenceServices.EndGetConferenceSummaries(asyncResetStatic);
 
            if (summaries == null)
            {
                CreatStaticConference();
                Trace("Doesnt Exist Creating static");
                return "Didnt Exist, Creating";
            }
            else
            {
                CancelMeetingStatic(summaries[0].ConferenceId);
                CreatStaticConference();
                Trace("Existed reset");
                return "Existed reset";
            }

                
            
        }

        private void Trace(string msg)
        {
            if (this.verbose)
            {
               // Console.Out.WriteLine(msg);
                Debug.WriteLine(msg);
            }
        }

        void selfDestruct_Elapsed(object sender, ElapsedEventArgs e)
        {
            this.Dispose();
        }

         public void Dispose()
         { 
            Dispose(true);
            GC.SuppressFinalize(this);           
         }

        // Protected implementation of Dispose pattern. 
        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
                return; 

            //Free managed Objects
            if (disposing) {
                try
                {
                    this.Trace("Terminate Endpoint");
                    IAsyncResult asyncResult = _userEndpoint.BeginTerminate(null, null);
                    _userEndpoint.EndTerminate(asyncResult);
                    this.selfDestruct.Dispose();
                }
                catch (Exception exception)
                {
                    this.Trace(exception.ToString());
                }
                
                this.Trace("Terminated endpoint");
                this.Trace("Destroyed endpoint for" + _userUri);
            }

            // Free any unmanaged objects here. 
            disposed = true;
        }

        ~MeetingInstance()
        {
            Dispose(false);
        }

    }
}
